﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DogJson
{
    public unsafe class ReadJsonData
    {
        private static object mutex = new object();
        private static bool initialized = false;
        private static ReadJsonData _ins = null;

        public static JsonData StaticRead(string str)
        {
            if (!initialized)
            {
                lock (mutex)
                {
                    if (_ins == null)
                    {
                        _ins = new ReadJsonData();
                        initialized = true;
                    }
                }
            }
           return _ins.Read(str);
        }

        public unsafe ReadJsonData(int jsonStackLength = 1024)
        {
            jsonDataStack = new JsonData[jsonStackLength];
            startStack = new bool[jsonStackLength];

            fixed (char* vs = "true")
            {
                truelong = *(long*)vs;
            }
            fixed (char* vs = "fals")
            {
                falslong = *(long*)vs;
            }
            fixed (char* vs = "null")
            {
                nulllong = *(long*)vs;
            }
            fixed (char* vs = "alse")
            {
                alselong = *(long*)vs;
            }
        }
        long truelong;
        long falslong;
        long nulllong;
        long alselong;

        JsonData[] jsonDataStack;

        bool[] startStack;

        int stackIndex = 0;

        int keyStringStart = 0;
        int keyStringLength = 0;
        int vStringStart = 0;
        int vStringLength = 0;

        public unsafe JsonData Read(string str)
        {
            JsonData root = null;

            int length = str.Length;
            fixed (char* vs = str)
            {
                char* now = vs;
                stackIndex = 0;
                keyStringLength = 0;
                keyStringStart = 0;
                double v_double = 0;
                double v_decimal = 1;
                long v_long = 0;
                JsonData json_object;

                int i = 0;
                //先读初始状态 这里 先只支持{开头的数据
                for (; i < length; ++i, ++now)
                {
                    switch (*now)
                    {
                        case '{':
                            root = new JsonData(new Dictionary<string, JsonData>());
                            startStack[++stackIndex] = true;
                            jsonDataStack[stackIndex] = root;

                            goto Run;
                        case ' ':
                        case '\t':
                        case '\r':
                        case '\n':
                            break;

                        case '"':
                        case ':':
                        case '}':
                        case '[':
                        case ']':
                        case ',':
                        default:
                            throw new Exception("错误开头" + *now);
                    }
                }
            Run:

            Loop:
                if (startStack[stackIndex])
                {
                    goto State_Object;
                }
                else
                {
                    goto State_Array;
                }

            State_Object:
                //下一个必出" 或}
                for (++i, ++now; i < length; ++i, ++now)
                {
                    switch (*now)
                    {
                        case '"':
                            keyStringStart = i + 1;
                            //再找" 
                            for (++i, ++now; i < length; ++i, ++now)
                            {
                                if (*now == '"')
                                {
                                    keyStringLength = i - keyStringStart;
                                    for (++i, ++now; i < length; ++i, ++now)
                                    {
                                        if (*now == ':')
                                        {
                                            goto Run1;
                                        }
                                    }
                                    throw new Exception("key后面需要:");
                                }
                            }
                            throw new Exception("字符串未结束 ");
                        case '}':
                            //出栈 
                            --stackIndex;
                            goto Loop;
                        case ' ':
                        case '\t':
                        case '\r':
                        case '\n':
                        case ',':
                            break;
                        default:
                            throw new Exception("对象 下面只能有keyvalue结构");
                    }
                }
            Run1:
                //key:后面只能是 布尔、数值、对象 、数组 再找下 " { [ 其他  不能是 } : , ]  

                for (++i, ++now; i < length; ++i, ++now)
                {
                    switch (*now)
                    {
                        case '"':
                            vStringStart = i + 1;

                            for (++i, ++now; i < length; ++i, ++now)
                            {
                                if (*now == '"')
                                {
                                    vStringLength = i - vStringStart;
                                    goto Run2;
                                }
                            }
                            throw new Exception("字符串未结束 ");
                        Run2:
                            // 下必 ,} 
                            for (++i, ++now; i < length; ++i, ++now)
                            {
                                switch (*now)
                                {
                                    case '}':
                                        //string入队
                                        json_object = new JsonData(new string(vs, vStringStart, vStringLength));

                                        jsonDataStack[stackIndex][new string(vs, keyStringStart, keyStringLength)] = json_object;
                                        //出栈 
                                        --stackIndex;
                                        goto Loop;
                                    case ',':
                                        //string入队
                                        json_object = new JsonData(new string(vs, vStringStart, vStringLength));
                                        jsonDataStack[stackIndex][new string(vs, keyStringStart, keyStringLength)] = json_object;
                                        goto State_Object;
                                    case ' ':
                                    case '\t':
                                    case '\r':
                                    case '\n':
                                        break;
                                    default:
                                        throw new Exception("key:value后面只能是,或者}" + *now);
                                }
                            }
                            throw new Exception("key:value后面必须要跟,或者} 未正常 结尾");

                        case '{':
                            //新建object赋予string名字 object入栈
                            json_object = new JsonData(new Dictionary<string, JsonData>());
                            jsonDataStack[stackIndex][new string(vs, keyStringStart, keyStringLength)] = json_object;

                            startStack[++stackIndex] = true;
                            jsonDataStack[stackIndex] = json_object;
                            goto State_Object;

                        case '[':
                            //新建array赋予string名字 array入栈
                            json_object = new JsonData(new List<JsonData>());
                            jsonDataStack[stackIndex][new string(vs, keyStringStart, keyStringLength)] = json_object;

                            startStack[++stackIndex] = false;
                            jsonDataStack[stackIndex] = json_object;
                            goto State_Array;


                        case 't':
                            if (i < length + 4)
                            {
                                long nameLong = *(long*)(now);
                                if (nameLong == truelong)
                                {
                                    json_object = new JsonData(true);
                                    now += 4;
                                    i += 4;
                                    goto Value;
                                }
                            }
                            throw new Exception("key:后面的value解析错误");
                        case 'n':
                            if (i < length + 4)
                            {
                                long nameLong = *(long*)(now);
                                if (nameLong == nulllong)
                                {
                                    json_object = new JsonData();
                                    now += 4;
                                    i += 4;
                                    goto Value;
                                }
                            }
                            throw new Exception("key:后面的value解析错误");
                        case 'f':
                            if (i < length + 4)
                            {
                                ++now;
                                ++i;
                                long nameLong = *(long*)(now);
                                if (nameLong == alselong)
                                {
                                    json_object = new JsonData(false);
                                    now += 4;
                                    i += 4;
                                    goto Value;
                                }
                            }
                            throw new Exception("key:后面的value解析错误");
                        default:
                            if (*now < 48 || *now > 57)
                            {
                                throw new Exception("key:value后面必须要跟,或者}" + *now);
                            }
                            v_long = (*now - 48);
                            for (++i, ++now; i < length; ++i, ++now)
                            {
                                if (*now < 48 || *now > 57)
                                {
                                    if (*now == '.')
                                    {
                                        goto Dot;
                                    }
                                    else
                                    {
                                        json_object = new JsonData(v_long);
                                        goto Value;
                                    }
                                }
                                else
                                {
                                    v_long *= 10;
                                    v_long += (*now - 48);
                                }
                            }
                            //long
                            throw new Exception("key:value后面必须要跟,或者}" + *now);

                        Dot:
                            v_double = v_long;
                            //点
                            v_decimal = 0.1;
                            for (++i, ++now; i < length; ++i, ++now)
                            {
                                if (*now < 48 || *now > 57)
                                {
                                    break;
                                }
                                else
                                {
                                    v_double += (*now - 48) * v_decimal;
                                    v_decimal *= 0.1;
                                }
                            }
                            json_object = new JsonData(v_double);

                        Value:

                            for (; i < length; ++i, ++now)
                            {
                                switch (*now)
                                {
                                    case ' ':
                                    case '\t':
                                    case '\r':
                                    case '\n':
                                        break;

                                    case ',':
                                        jsonDataStack[stackIndex][new string(vs, keyStringStart, keyStringLength)] = json_object;

                                        goto State_Object;
                                    case '}':
                                        jsonDataStack[stackIndex][new string(vs, keyStringStart, keyStringLength)] = json_object;
                                        //出栈 
                                        --stackIndex;
                                        goto Loop;
                                    default:
                                        throw new Exception("key:value后面必须要跟,或者} ,");
                                }
                            }
                            throw new Exception("key:value后面必须要跟,或者} ,未正常结尾");

                        case ' ':
                        case '\t':
                        case '\r':
                        case '\n':
                            break;

                        case ':':
                        case '}':
                        case ',':
                        case ']':
                            throw new Exception("key:后面不能是" + *now);
                    }
                }

            State_Array:
                //" ]
                for (++i, ++now; i < length; ++i, ++now)
                {
                    switch (*now)
                    {
                        case '"':
                            vStringStart = i + 1;
                            //再找" 
                            for (++i, ++now; i < length; ++i, ++now)
                            {
                                if (*now == '"')
                                {
                                    vStringLength = i - vStringStart;
                                    for (++i, ++now; i < length; ++i, ++now)
                                    {
                                        //必出 , ]
                                        if (*now == ',')
                                        {
                                            json_object = new JsonData(new string(vs, vStringStart, vStringLength));
                                            jsonDataStack[stackIndex].Add(json_object);
                                            goto State_Array;
                                        }
                                        else if (*now == ']')
                                        {
                                            json_object = new JsonData(new string(vs, vStringStart, vStringLength));
                                            jsonDataStack[stackIndex].Add(json_object);
                                            //出栈 
                                            --stackIndex;
                                            goto Loop;
                                        }
                                    }
                                    throw new Exception("key后面需要:");
                                }
                            }
                            throw new Exception("字符串未结束 ");

                        case '{':
                            // { 新建 object 入栈
                            json_object = new JsonData(new Dictionary<string, JsonData>());
                            jsonDataStack[stackIndex].Add(json_object);

                            startStack[++stackIndex] = true;
                            jsonDataStack[stackIndex] = json_object;

                            goto State_Object;
                        //goto Loop;

                        case '[':
                            // [新建 array 入栈
                            json_object = new JsonData(new List<JsonData>());
                            jsonDataStack[stackIndex].Add(json_object);

                            startStack[++stackIndex] = false;
                            jsonDataStack[stackIndex] = json_object;

                            goto State_Array;
                        case 't':
                            if (i < length + 4)
                            {
                                long nameLong = *(long*)(now);
                                if (nameLong == truelong)
                                {
                                    json_object = new JsonData(true);
                                    now += 4;
                                    i += 4;
                                    goto Value2;
                                }
                            }
                            throw new Exception("key:后面的value解析错误");
                        case 'n':
                            if (i < length + 4)
                            {
                                long nameLong = *(long*)(now);
                                if (nameLong == nulllong)
                                {
                                    json_object = new JsonData();
                                    now += 4;
                                    i += 4;
                                    goto Value2;
                                }
                            }
                            throw new Exception("key:后面的value解析错误");
                        case 'f':
                            if (i < length + 4)
                            {
                                ++now;
                                ++i;
                                long nameLong = *(long*)(now);
                                if (nameLong == alselong)
                                {
                                    json_object = new JsonData(false);
                                    now += 4;
                                    i += 4;
                                    goto Value2;
                                }
                            }
                            throw new Exception("key:后面的value解析错误");
                        default:
                            if (*now < 48 || *now > 57)
                            {
                                throw new Exception("key:value后面必须要跟,或者}" + *now);
                            }
                            v_long = (*now - 48);
                            for (++i, ++now; i < length; ++i, ++now)
                            {
                                if (*now < 48 || *now > 57)
                                {
                                    if (*now == '.')
                                    {
                                        goto Dot2;
                                    }
                                    else
                                    {
                                        json_object = new JsonData(v_long);
                                        goto Value2;
                                    }
                                }
                                else
                                {
                                    v_long *= 10;
                                    v_long += (*now - 48);
                                }
                            }
                            //long
                            throw new Exception("key:value后面必须要跟,或者}" + *now);

                        Dot2:
                            v_double = v_long;
                            //点
                            v_decimal = 0.1;
                            for (++i, ++now; i < length; ++i, ++now)
                            {
                                if (*now < 48 || *now > 57)
                                {
                                    break;
                                }
                                else
                                {
                                    v_double += (*now - 48) * v_decimal;
                                    v_decimal *= 0.1;
                                }
                            }
                            json_object = new JsonData(v_double);
                        Value2:

                            for (; i < length; ++i, ++now)
                            {
                                switch (*now)
                                {
                                    case ' ':
                                    case '\t':
                                    case '\r':
                                    case '\n':
                                        break;

                                    case ',':
                                        jsonDataStack[stackIndex].Add(json_object);
                                        goto State_Array;
                                    case ']':
                                        jsonDataStack[stackIndex].Add(json_object);
                                        //出栈 
                                        --stackIndex;
                                        goto Loop;
                                    default:
                                        throw new Exception("key:value后面必须要跟,或者} ,");
                                }
                            }
                            throw new Exception("key:value后面必须要跟,或者} ,未正常结尾");

                        case ' ':
                        case '\t':
                        case '\r':
                        case '\n':
                        case ',':
                            break;
                        case ']':
                            //出栈 
                            --stackIndex;
                            goto Loop;

                        case ':':
                        case '}':
                            throw new Exception("key:后面不能是" + *now);
                    }
                }

                return root;//jsonStackIndex
            }

        }





    }
}
